#include "NAudioManager.h"
#include "NeroCore\NMemoryManager.h"
#include "NEngineException.h"

#pragma comment(lib,"OpenAL32.lib")
using namespace Engine;

NAudioManager* NAudioManager::sInstance = NULL;

NAudioManager::NAudioManager(void)
{
	TurnOnAudioSystem();
	LoadAudio("Footsteps.wav");
}

NAudioManager::~NAudioManager(void)
{
	ShutDownAudioSystem();
}

void NAudioManager::Initialize()
{
#ifndef DISABLE_AUDIO
	if(!sInstance)
	{
		sInstance = MY_NEW(Memory::HID_Engine,"Audio Manager") NAudioManager();
	}
#endif
}

void NAudioManager::Deinitialize()
{
	if(sInstance)
	{
		MY_DELETE(sInstance);
		sInstance = NULL;
	}
}

NAudioManager* NAudioManager::GetInstance()
{
	if(!sInstance)
	{
		throw NEngineException("NAudioManager - Not Initialized");
	}
	return sInstance;
}

void NAudioManager::TurnOnAudioSystem()
{
	// Initialize Framework
	ALFWInit();

	if (!ALFWInitOpenAL())
	{
		ALFWprintf("Failed to initialize OpenAL\n");
		ALFWShutdown();
		throw Engine::NEngineException("Failed to initialize OpenAL\n");
	}

	ALFWprintf("Initialized Audio System\n");
}

void NAudioManager::ShutDownAudioSystem()
{
	AudioSources::iterator _it = mAudioSourceList.begin();
		for(; _it != mAudioSourceList.end(); _it++)
		{
			DestroyAudioEvent(*_it);
		}

	ALFWShutdownOpenAL();

	ALFWShutdown();
}

void NAudioManager::PlaySFX(const char* file)
{
	AudioSources::iterator _it = mAudioSourceList.begin();
	for(; _it != mAudioSourceList.end(); _it++)
	{
		if(strcmp(_it->file.c_str(),file) == 0)
		{
			_it->Action = AudioAction_Play;
		}
	}
}

void NAudioManager::Update(float)
{
	if(mAudioSourceList.size() > 0)
	{
		AudioSources::iterator _it = mAudioSourceList.begin();
		for(; _it != mAudioSourceList.end(); _it++)
		{
			switch (_it->Action)
			{
			case AudioAction_Play:
				// Play Source
				alSourcePlay( _it->Source );

				_it->Action = AudioAction_None;

				break;

			case AudioAction_Pause:

				break;

			case AudioAction_Stop:

				break;

			case AudioAction_Remove:
				break;

			default:
				break;
			}
		}
		
		ALint iState;
		_it = mAudioSourceList.begin();

		for(; _it != mAudioSourceList.end(); _it++)
		{
			alGetSourcei( _it->Source, AL_SOURCE_STATE, &iState);

			switch (iState)
			{
			case AL_PLAYING:
				break;
			case AL_PAUSED:
				break;
			case AL_STOPPED:

				_it->Action = AudioAction_Remove;

				break;
			default:
				break;
			}
		}
	}
}

void NAudioManager::LoadAudio(const char* file)
{
	AudioEvent aEvent;

	// Generate an AL Buffer
	alGenBuffers( 1, &aEvent.Buffer );

	// Load Wave file into OpenAL Buffer
	if (!ALFWLoadWaveToBuffer((char*)ALFWaddMediaPath(file), aEvent.Buffer))
	{
		ALFWprintf("Failed to load %s\n", ALFWaddMediaPath(file));
	}

	aEvent.file = file;

	// Generate a Source to playback the Buffer
    alGenSources( 1, &aEvent.Source );

	// Attach Source to Buffer
	alSourcei( aEvent.Source, AL_BUFFER, aEvent.Buffer );

	aEvent.Action = AudioAction_Pause;

	mAudioSourceList.push_back(aEvent);
}

void NAudioManager::DestroyAudioEvent(AudioEvent aEvent)
{
	// Clean up by deleting Source(s) and Buffer(s)
	alSourceStop(aEvent.Source);
    alDeleteSources(1, &aEvent.Source);
	alDeleteBuffers(1, &aEvent.Buffer);
}